﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

namespace WpfApplication1
{
    public static class EnumHelper
    {
        public static string GetDescription(this Enum value)
        {
            var fieldInfo = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(
                                                         typeof(DescriptionAttribute),
                                                         false);

            return attributes.Length > 0
                       ? attributes[0].Description
                       : null;
        }

        public static EnumType GetValueByDescription<EnumType>(string description) where EnumType : struct, IComparable, IFormattable, IConvertible
        {
            var type = typeof(EnumType);
            if (!type.IsEnum)
                throw new ArgumentException("This method is destinated for enum types only.");
            foreach (var enumName in Enum.GetNames(type))
            {
                var enumValue = Enum.Parse(type, enumName);
                if (description == ((Enum)enumValue).GetDescription())
                    return (EnumType)enumValue;
            }
            throw new ArgumentException("There is no value with this description among specified enum type values.");
        }

        public static List<string> GetAllDescriptions<TEnum>() where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var enumType = typeof(TEnum);
            if (!enumType.IsEnum)
            {
                throw new ArgumentException("T must be of type System.Enum");
            }
            FieldInfo[] fieldInfos = enumType.GetFields();
            List<string> descriptions = new List<string>(fieldInfos.Length);
            foreach (var fieldInfo in fieldInfos)
            {
                var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(
                                                       typeof(DescriptionAttribute),
                                                       false);
                if (attributes.Length > 0)
                {
                    descriptions.Add(attributes[0].Description);
                }
                //else
                //{ //似乎会将System.Enum中的字段也反射出来了  哎 ;灵光一闪被扼杀
                //    throw new NotImplementedException(string.Format("Enum Field {0} not implement Description Attribute", fieldInfo.Name));
                //}
            }
            descriptions.TrimExcess();
            return descriptions;
        }

        /// <summary>
        /// Returns an enumerable collection of all values and descriptions for an enum type.
        /// 配合下面的 ValueDescription类使用 ;将枚举类型绑定到WPF中的ComboBox上
        /// </summary>
        public static IEnumerable<ValueDescription> GetAllValuesAndDescriptions<TEnum>() where TEnum : struct, IConvertible, IComparable, IFormattable
        {
            if (!typeof(TEnum).IsEnum)
                throw new ArgumentException("TEnum must be an Enumeration type");

            return from e in Enum.GetValues(typeof(TEnum)).Cast<Enum>()
                   select new ValueDescription() { Value = e, Description = e.GetDescription() };
        }


        #region Parse --->可考虑作为string类的扩展方法来使用！！

        public static T Parse<T>(string value) where T : struct, IComparable, IFormattable, IConvertible
        {//EnumHelper.Parse<Fabric>("cotton",false).Dump()
            return EnumHelper.Parse<T>(value, true);
        }
        public static T Parse<T>(string value, bool ignoreCase)
        {
            return (T)Enum.Parse(typeof(T), value, ignoreCase);
        }

        public static bool TryParse<T>(string value, out T returnedValue)
        {
            return EnumHelper.TryParse<T>(value, true, out returnedValue);
        }
        public static bool TryParse<T>(string value, bool ignoreCase, out T returnedValue)
        {
            try
            {
                returnedValue = (T)Enum.Parse(typeof(T), value, ignoreCase);
                return true;
            }
            catch
            {
                returnedValue = default(T);
                return false;
            }
        }
        #endregion

    }

    public class ValueDescription
    { 
        /// <summary>
        /// 枚举子项值
        /// </summary>
        public Enum Value { get; set; }
        /// <summary>
        /// 枚举项上的特性Description中值
        /// </summary>
        public string Description { get; set; }
    }
}
